"""Auth utilities"""
import hashlib
from datetime import datetime, timedelta
from typing import Optional

import bcrypt
import jwt

from .config import ServeConfig


class PasswordUtils:
    """Password utilities"""

    @staticmethod
    def hash_password(password: str, rounds: int = 12) -> str:
        """Hash password using bcrypt"""
        salt = bcrypt.gensalt(rounds=rounds)
        hashed = bcrypt.hashpw(password.encode("utf-8"), salt)
        return hashed.decode("utf-8")

    @staticmethod
    def verify_password(password: str, hashed: str) -> bool:
        """Verify password"""
        try:
            return bcrypt.checkpw(password.encode("utf-8"), hashed.encode("utf-8"))
        except Exception:
            return False


class JWTUtils:
    """JWT utilities"""

    @staticmethod
    def create_token(
        user_id: int,
        username: str,
        config: ServeConfig,
        expires_delta: Optional[timedelta] = None,
    ) -> str:
        """Create JWT token"""
        if expires_delta is None:
            expires_delta = timedelta(minutes=config.jwt_expire_minutes)

        expire = datetime.utcnow() + expires_delta
        payload = {
            "user_id": user_id,
            "username": username,
            "exp": expire,
            "iat": datetime.utcnow(),
        }

        token = jwt.encode(
            payload, config.jwt_secret_key, algorithm=config.jwt_algorithm
        )
        return token

    @staticmethod
    def decode_token(token: str, config: ServeConfig) -> Optional[dict]:
        """Decode JWT token"""
        try:
            payload = jwt.decode(
                token,
                config.jwt_secret_key,
                algorithms=[config.jwt_algorithm],
            )
            return payload
        except jwt.ExpiredSignatureError:
            return None
        except jwt.InvalidTokenError:
            return None

    @staticmethod
    def get_token_expire_seconds(config: ServeConfig) -> int:
        """Get token expiration time in seconds"""
        return config.jwt_expire_minutes * 60
